package portal.action.rest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;

import beans.BaseResourceState;
import beans.FullJobState;
import beans.HistoryJob;
import beans.HistoryTask;
import beans.HttpConfig;
import beans.HttpResult;
import beans.HttpResultList;
import dao.HistoryTaskDao;
import dao.TaskDao;
import engine.BIEngine0_1.AlgorithmOperator;
import portal.cmd.JHCmd;
import portal.cmd.beans.ResourceBean;
import portal.common.MyStringUtils;
import portal.engine.JobOperator;
import utils.Log4jInit;

@RequestMapping(value = "/ws/")
@RestController
public class ScheduleAction {
	@Autowired
	JHCmd jhCmd;

	@RequestMapping(value = "/source/release", method = RequestMethod.GET)
	public JSONObject releaseSoruce(String modelId) {
		Log4jInit.logger.info("======start release=======");
		JSONObject jb = new JSONObject();
		jb.put("result", false);
		jb.put("message", "模型ID无效，非DPGrid模式模型");
		if (modelId == null || modelId.length() == 0)
			return null;
		if (!HttpConfig.modelIds.contains("#" + modelId + "#"))
			return null;

		// find the current taskid by modelId
		int taskId = TaskDao.getCurrentTask(Integer.parseInt(modelId));
		Log4jInit.logger.info("======start release  taskid=======" + taskId);
		int flag=0;
		if (taskId > 0) {
			// HistoryTaskDao.getTaskFinishState(taskId);
			List<Object> hisTaskList = HistoryTaskDao.getHisTaskByTaskid(taskId);
			String taskHash = "";
			HttpResult tokenResult = AlgorithmOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
			String token = "";
			if (tokenResult.isResult()) {
				token = tokenResult.getMessage();
			} else {
				jb.put("result", false);
				jb.put("message", "token获取失败");
				return jb;
			}
			Log4jInit.logger.info("====== release  token =======" + token);
			Log4jInit.logger.info("====== release  hisTaskList.size()=======" + hisTaskList.size());
			for (int m = 0; m < hisTaskList.size(); m++) {
				HistoryTask ht = (HistoryTask) hisTaskList.get(m);
				if (ht.getBatch_task_hash()==null){
					taskHash = ht.getTask_hash();	
					continue;
				}else{
					jb = killJobAndUpdDB(ht.getTask_hash(), token);
					Log4jInit.logger.info("-------jb killJobAndUpdDB  "+jb.getString("message"));
					if(jb.getInteger("result")!=0){
						flag = jb.getInteger("result");
					}
				}
			}
		}
		/*
		 * String host[]= modelId.split(","); for(String h:host){
		 * jhCmd.hostOpen(h); }
		 */
		if (flag==0) {
			jb.put("result", true);
			jb.put("message", "资源释放成功");
			return jb;
		}
		jb.put("result", false);
		jb.put("message", "资源释放失败");
		return jb;
	}

	@RequestMapping(value = "/source/apply", method = RequestMethod.GET)
	public JSONObject applyResources(Integer num, Integer cpu, Integer mem) {
		if (num == null)
			return JSONObject.parseObject("{'result':false,'message':'num 不能为空'}");
		if (cpu == null)
			cpu = 0;
		if (mem == null)
			mem = 0;
		List<ResourceBean> list = new ArrayList<>();
		loadAvaiableHost(list);
		loadResoureUsage(list);
		return checkCondition(list, num, cpu, mem);
		//
	}

	/**
	 * HZJ-190701 Stop the subTasks, kill jobs,open host,update DB
	 * 
	 * @param task_hash
	 * @return
	 */
	private JSONObject killJobAndUpdDB(String task_hash, String token) {
		// TODO Auto-generated method stub
		JSONObject rt = new JSONObject();
		if(task_hash==null || task_hash.equals("")){
			rt.put("result", -1);
			rt.put("message", "taskHash is NULL");
			return rt;
		}
		Log4jInit.logger.info("----release----killJobAndUpdDB---task_hash:" + task_hash);
		List<Object> list = HistoryTaskDao.getSubTaskByTaskHash(task_hash);
		for (int i = 0; i < list.size(); i++) {
			HistoryJob hj = (HistoryJob) list.get(i);
			Log4jInit.logger.info("----release--hj.getJobId:" + hj.getJobId());
			if ((!MyStringUtils.isEmpty(hj.getJobId() + "")) && killJob(hj.getJobId())) {
				Log4jInit.logger.info("---------" + hj.getJobId());
				try {
					HttpResultList result = AlgorithmOperator.getJobFullState(hj.getJobId() + "", token);
					FullJobState fullJobState = (FullJobState) result.getDatas().get(0);
					String executionHost = fullJobState.getExecutionHost().split("]")[0].replaceAll("[\"\\[]", "");
					Log4jInit.logger.info("----release--executionHost: " + executionHost);
					boolean b =jhCmd.hostOpen(executionHost);
					Log4jInit.logger.info("----release--executionHost RESULT: " + b);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				boolean jobs = HistoryTaskDao.updateJobAfterKilljob(hj.getTaskHash());
				Log4jInit.logger.info("----release--jobs int:" + jobs);
				if (!jobs){
					rt.put("result", 1);
					rt.put("message", "history_job更新失败");
					return rt;
				}
			}else{
				rt.put("result", -2);
				rt.put("message", "killing fail");
			}
			
		}
		boolean tk = HistoryTaskDao.updateTaskAfterKilljob(task_hash);
		Log4jInit.logger.info("----release--tk int:" + tk);
		if (!tk){
			rt.put("result", 2);
			rt.put("message", "history_task更新失败");
			return rt;
		}
		rt.put("result", 0);
		rt.put("message", "OK");
		return rt;
	}

	/**
	 * kill the job by command
	 * 
	 * @param jobid
	 * @return
	 */
	private boolean killJob(int jobid) {

		return jhCmd.killJob(jobid + "");
	}

	/******
	 * get Hosts avaliable with command jhosts
	 *********/
	private void loadAvaiableHost(List<ResourceBean> list) {
		if (list == null)
			list = new ArrayList<>();
		String[] data = jhCmd.jhosts().split("\n");
		for (String s : data) {
			if (s == data[0]) {
				if (s.startsWith("HOST_NAME"))
					continue;
				break;
			}
			String[] detail = MyStringUtils.strictSpace(s).split(" ");
			if ("ok".equals(detail[1]) && "0".equals(detail[5])) {
				ResourceBean cb = new ResourceBean(detail[0]);
				list.add(cb);
			}
		}
	}

	/*******
	 * Get Node Resoure Usge With webservice
	 * 
	 ******/
	private void loadResoureUsage(List<ResourceBean> list) {
		HttpResult tokenResult = JobOperator.getToken(HttpConfig.userName, HttpConfig.passWord);
		String token = null;
		if (tokenResult.isResult()) {
			token = tokenResult.getMessage();

			// 基础设施资源监控，获取全部基础设施资源信息
			HttpResultList httpResultList = AlgorithmOperator.getJobBasicState(token);
			for (int i = 0; i < httpResultList.getDatas().size(); i++) {
				BaseResourceState brs = (BaseResourceState) httpResultList.getDatas().get(i);
				for (ResourceBean rb : list) {
					if (rb.getHostName().equals(brs.getHostName())) {
						rb.setCpu(brs.getUt());
						rb.setMemT(brs.getMem());
					}
				}
			}
		}
	}

	/*****
	 * check node fit conditions
	 ***/
	public JSONObject checkCondition(List<ResourceBean> list, int num, int cpu, int mem) {
		JSONObject jb = new JSONObject();
		String nodes = "";
		int i = 0;
		for (ResourceBean b : list) {
			if (b.getHostName().startsWith("master"))
				continue;
			if (b.isAvaliable(mem, cpu)) {
				// nodes[i++]=b.getHostName();
				nodes = nodes + b.getHostName() + ",";
				i++;
				if (i >= num)
					break;
			}
		}
		if (num <= i)
			jb.put("result", true);
		else
			jb.put("result", false);
		jb.put("num", i);
		jb.put("nodes", nodes);
		return jb;
	}

	// @RequestMapping(value="/source/apply" ,method=RequestMethod.GET)
	public JSONObject applyResource(Integer num, Integer cpu, Integer mem) {
		if (num == null)
			return JSONObject.parseObject("{'result':false,'message':'num 不能为空'}");
		if (cpu == null)
			cpu = 0;
		if (mem == null)
			mem = 0;

		List<CmdBean> list = new ArrayList<>();
		// jhCmd jhosts -l stat -I
		checkNodes(list);
		// String nodes[]=new String[list.size()];
		String nodes = "";
		int i = 0;
		for (CmdBean b : list) {
			if (b.getHostName().startsWith("master"))
				continue;
			if (b.isAvaliable(num, cpu, mem)) {
				// nodes[i++]=b.getHostName();
				nodes = nodes + b.getHostName() + ",";
				i++;
			}
		}
		JSONObject jb = new JSONObject();
		if (num <= i)
			jb.put("result", true);
		else
			jb.put("result", false);
		jb.put("num", i);
		jb.put("nodes", nodes);
		Log4jInit.logger.info(jb.toString());
		// jhCmd jhosts -l attrib
		// 计算节点，并返回符合条件节点信息
		return jb;
	}

	private void checkNodes(List<CmdBean> list) {
		if (jhCmd == null)
			jhCmd = new JHCmd();
		String[] data = jhCmd.jhosts_list_stat().split("\n");
		for (String s : data) {
			if (s == data[0]) {
				if (s.startsWith("HOST_NAME"))
					continue;
				break;
			}
			CmdBean cb = new CmdBean();
			cb.setCpuAndMemU(s);
			list.add(cb);
		}
		data = jhCmd.jhosts_attrib().split("\n");
		for (String s : data) {
			if (s == data[0]) {
				if (s.startsWith("HOST_NAME"))
					continue;
				break;
			}
			for (CmdBean b : list) {
				if (b.setMemT(s))
					break;
			}
		}
	}

	public static void main(String[] args) {
		ScheduleAction s1 = new ScheduleAction();
		s1.applyResource(1, 1, 1);
	}
}

class CmdBean {
	String hostName = null;
	int cpu = 100;
	int memU = Integer.MAX_VALUE;
	int memT;
	int core = 0;
	String status;

	public String getHostName() {
		return hostName;
	}

	public boolean setCpuAndMemU(String data) {
		return setCpuAndMemU(MyStringUtils.strictSpace(data).split(" "));
	}

	public boolean setCpuAndMemU(String[] data) {
		if (hostName == null)
			hostName = data[0];
		if (!hostName.equals(data[0]))
			return false;
		status = data[1];
		cpu = Integer.valueOf(data[5].replace("%", ""));
		if (data[12].endsWith("M"))
			memU = Integer.valueOf(data[12].replace("M", ""));
		else if (data[12].endsWith("G"))
			memU = (int) (Float.valueOf(data[12].replace("G", "")) * 1024);
		return true;
	}

	public boolean setMemT(String data) {
		return setMemT(MyStringUtils.strictSpace(data).split(" "));
	}

	public boolean setMemT(String[] data) {
		if (hostName == null)
			hostName = data[0];
		if (!hostName.equals(data[0]))
			return false;
		if (data[5].endsWith("M"))
			memT = Integer.valueOf(data[5].replace("M", ""));
		else if (data[5].endsWith("G"))
			memT = (int) (Float.valueOf(data[5].replace("G", "")) * 1024);
		core = Integer.valueOf(data[9]);
		///
		return true;
	}

	public boolean isCpu(int c) {
		if ((100 - cpu) >= c)
			return true;
		return false;
	}

	public boolean isMem(int m) {
		if ((memT - memU) >= m)
			return true;
		return false;
	}

	public boolean isCore(int c) {
		if (core >= c)
			return true;
		return false;
	}

	public boolean isAvaliable(int core, int cpu, int mem) {
		// if(false==this.isCore(core))
		// return false;
		if (false == this.isCpu(cpu))
			return false;
		if (false == this.isMem(mem))
			return false;
		return true;
	}

}